package cwinsor.com.leaf_raking;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import cwinsor.com.leaf_raking.Person.Format;

public class FileTypeState extends FileType {

	/* 
	 * local variables - column numbers
	 */
	protected Integer colSkip;

	protected Integer colPersonType;
	protected Integer colFirstName;
	protected Integer colLastName;
	protected Integer colGender;
	protected Integer colVarNovCox;
	protected Integer colGrade;
	protected Integer colPower;

	protected Integer colAvailLastBase;
	protected Integer colAvailLastTop;
	protected Integer colAvailCurrentBase;
	protected Integer colAvailCurrentTop;
	protected Integer colAssignmentCurrentBase;
	protected Integer colAssignmentCurrentTop;
	protected Integer colAddDropBase;
	protected Integer colAddDropTop;

	protected Integer colPhoneC;
	protected Integer colPhoneH;
	protected Integer colEnd;


	/**
	 * constructor
	 */
	public FileTypeState() {

		// establish column numbers
		colSkip = 0;
		colPersonType = 1;
		colFirstName = 2;
		colLastName = 3;
		colGender = 4;
		colVarNovCox = 5;
		colGrade = 6;
		colPower = 7;

		colAvailLastBase = colPower + 1;
		colAvailLastTop = colAvailLastBase + WorkShift.size()-1;
		colAvailCurrentBase = colAvailLastTop + 1;
		colAvailCurrentTop = colAvailCurrentBase + WorkShift.size()-1;
		colAssignmentCurrentBase = colAvailCurrentTop + 1;
		colAssignmentCurrentTop = colAssignmentCurrentBase + WorkShift.size()-1;
		colAddDropBase = colAssignmentCurrentTop + 1;
		colAddDropTop = colAddDropBase + WorkShift.size()-1;

		colPhoneC = colAddDropTop + 1;
		colPhoneH = colPhoneC + 1;
		colEnd = colPhoneH + 1;
	}


	// name
	public String getName() { return "FileTypeState"; }

	///////////////
	// column getters
	public Integer colSkip() { return colSkip; }
	public Integer colPersonType() { return colPersonType; }
	public Integer colFirstName() { return colFirstName; }
	public Integer colLastName() { return colLastName; }
	public Integer colGender() { return colGender; }
	public Integer colVarNovCox() { return colVarNovCox; }
	public Integer colGrade() { return colGrade; }
	public Integer colPower() { return colPower; }
	public Integer colAvailLast(WorkShift workShift) {
		return colAvailLastBase + workShift.toIndex();
	}
	public Integer colAvailCurrent(WorkShift workShift) {
		return colAvailCurrentBase + workShift.toIndex();
	}
	public Integer colAssignmentCurrent(WorkShift workShift) {
		return colAssignmentCurrentBase + workShift.toIndex();
	}

	public Integer colAddDrop(WorkShift workShift) {
		return colAddDropBase + workShift.toIndex();
	}

	public Integer colPhoneC() { return colPhoneC; }
	public Integer colPhoneH() { return colPhoneH; }
	public Integer colEnd() { return colEnd; }


	/*
	 * populate data from array of fields
	 */
	@Override
	public void doPopulate(
			ArrayList<String> theFieldsObject,
			ArrayList<Person> persons,
			Boolean supervisors) {

		Msg.note(dS + ": populating from line" + theFieldsObject.toString());

		// sanity checks
		// confirm there are enough fields
		if (theFieldsObject.size() != colEnd()+1) {
			Msg.fatal(dS + ": number of columns incorrect..."
					+ " last column (index) = " + colEnd()
					+ " but theFieldsObject.size() = "
					+ theFieldsObject.size()
					+ " (should be " + colEnd()+1);
		}
		// confirm the line ends with "END"
		if (!theFieldsObject.get(colEnd()).equals("END")) {
			Msg.fatal(dS + ": the last column (number " + colEnd() + ") should be \"END\"");
		}

		Person person = null;
		if (theFieldsObject.get(colPersonType()).equals("RAKER")) {
			// raker
			person = new PersonRaker();	
		}
		else if (theFieldsObject.get(colPersonType()).equals("SUPERVISOR")) {
			// supervisor
			person = new PersonSupervisor();	
		}		
		else {
			Msg.fatal(dS + ": hit the default case");
		}

		// process the input data
		person.setFirstName(theFieldsObject.get(colFirstName()));
		person.setLastName(theFieldsObject.get(colLastName()));
		person.setGender(theFieldsObject.get(colGender()));

		if      (theFieldsObject.get(colPower()).equals("1")) {
			person.setPower(1);
		}
		else if (theFieldsObject.get(colPower()).equals("2")) {
			person.setPower(2);
		}
		else if (theFieldsObject.get(colPower()).equals("3")) {
			person.setPower(3);
		}
		else if (theFieldsObject.get(colPower()).equals("4")) {
			person.setPower(4);
		}
		else if (theFieldsObject.get(colPower()).equals("5")) {
			person.setPower(5);
		}
		else if (theFieldsObject.get(colPower()).equals("-100")) {
			person.setPower(-100);
		}
		else {
			Msg.fatal(dS + ": unable to read column POWER from state file = is " + theFieldsObject.get(colPower()));
		}

		// availability, last availability, team assignment
		for (WorkShift workShift : WorkShift.asList()) {
			person.setAvailabilityCurrent(
					workShift,
					getIntegerValueOf(theFieldsObject, colAvailCurrent(workShift), true)
					);
			person.setAvailabilityLast(
					workShift,
					getIntegerValueOf(theFieldsObject,colAvailLast(workShift),true)
					);
			person.setAssignmentCurrent(
					workShift,
					TeamNumber.stringToTeam(theFieldsObject.get(colAssignmentCurrent(workShift)))
					);
			person.setAddDrop(workShift, 
					TeamChange.objectToTeamChange(theFieldsObject.get(colAddDrop(workShift)))
					);
		}

		person.setPhoneC(theFieldsObject.get(colPhoneC()));
		person.setPhoneH(theFieldsObject.get(colPhoneH()));
		persons.add(person);
	}


	@Override
	protected void doWriteToFile(Person person, PrintWriter writer,
			Format format) {

		Map<Integer,String> theFieldsObject = new HashMap<Integer,String>();

		//	toStringCommaDelimitedAllFieldsMid(theFieldsObject, format, person);
		toStringCommaDelimitedAllFieldsMid(theFieldsObject, format, person);

		String foo = new String();
		for (Integer i=0; i<=colEnd(); i++) {
			if (i!=0) {
				foo = foo + ",";	
			}
			if (theFieldsObject.get(i) != null) {
				foo = foo + theFieldsObject.get(i);
			} else {
				foo = foo + "-";
			}
		}
		writer.write(foo);
		writer.write("\n");
	}

	public void toStringCommaDelimitedAllFieldsMid(Map<Integer,String> theFieldsObject, Format fmt, Person person) {

		if (fmt==Format.SHORT_FORM) {
			theFieldsObject.put(0, "-");
			theFieldsObject.put(2, person.getFirstName());
			theFieldsObject.put(3, person.getLastName());
			theFieldsObject.put(4, person.getPhoneC());
			theFieldsObject.put(5, person.getPhoneH());	
			return;
		}

		if (fmt==Format.LONG_FORM) {
			theFieldsObject.put(colSkip(),"-");
			theFieldsObject.put(colPersonType(), person.getType());
			theFieldsObject.put(colFirstName(), person.getFirstName());
			theFieldsObject.put(colLastName(), person.getLastName());
			theFieldsObject.put(colGender(), person.getGender());
			theFieldsObject.put(colVarNovCox(),	person.getVarsityNovCox());
			theFieldsObject.put(colGrade(),	person.getGrade().toString());
			theFieldsObject.put(colPower(),	person.getPower().toString());

			// availability
			for (WorkShift workShift : WorkShift.asList()) {
				theFieldsObject.put(
						colAvailCurrent(workShift),
						person.getCurrentAvailability(workShift).toString()
						);
				theFieldsObject.put(
						colAvailLast(workShift),
						person.getLastAvailability(workShift).toString()
						);
				theFieldsObject.put(
						colAssignmentCurrent(workShift),
						person.getAssignmentCurrent(workShift).toStringSingleCharWithBlank()
						);
				theFieldsObject.put(
						colAddDrop(workShift),
						person.getAddDrop(workShift).toString()
						);
			}

			theFieldsObject.put(colPhoneC(), person.getPhoneC());
			theFieldsObject.put(colPhoneH(), person.getPhoneH());
			theFieldsObject.put(colEnd(), "END");
			return;
		}

		if (fmt==Format.CHANGE_SUMMARY) {
			theFieldsObject.put(0, person.getFirstName());
			theFieldsObject.put(1, person.getLastName());

			// availability
			Integer colNum = 2;
			for (WorkShift workShift : WorkShift.asList()) {
				theFieldsObject.put(colNum+0, person.getCurrentAvailability(workShift).toString());
				theFieldsObject.put(colNum+1, person.getLastAvailability(workShift).toString());
				theFieldsObject.put(colNum+2,
						(person.getAssignmentCurrent(workShift) == TeamNumber.TEAM_UNASSIGNED) ? "" : person.getAssignmentCurrent(workShift).toString());
				theFieldsObject.put(colNum+3, person.getAvailDelta(workShift).toString());
				colNum+=4;
			}

			theFieldsObject.put(colNum++, person.getAvailTotalChange().toString());
			theFieldsObject.put(colNum++, person.getHappiness().toString());
			return;
		}

		Msg.fatal(dS + "when converting Person to string - hit the default case - format=" + fmt);
		return;
	}


	@Override
	protected void doApplySchedulePreferenceUpdates(ArrayList<String> theFieldsObject,
			PrsnList personList) {

		Msg.fatal(dS + ": not supported");
	}


	// debug
	String dS = this.getClass().getSimpleName();
}

